//
// Created by WINDOWS on 2025/6/12.
//

#include "DirectoryMonitor.h"

namespace fs = std::filesystem;

//DirectorySpaceMonitor::DirectorySpaceMonitor(fs::path dir_path,
//                               std::chrono::seconds interval = std::chrono::seconds(1))
//        : dir_path_(std::move(dir_path)),
//          scan_interval_(interval),
//          running_(false),
//          total_size_(0) {
//
//    if (!fs::exists(dir_path_) || !fs::is_directory(dir_path_)) {
//        throw std::runtime_error("Invalid directory path");
//    }
//}

DirectorySpaceMonitor::~DirectorySpaceMonitor() {
    stop();
}

void DirectorySpaceMonitor::start() {
    if (running_) return;

    running_ = true;
    // 初始扫描
    initial_scan();
    // 启动监控线程
    monitor_thread_ = std::thread(&DirectorySpaceMonitor::monitor_loop, this);
}

void DirectorySpaceMonitor::stop() {
    running_ = false;
    if (monitor_thread_.joinable()) {
        monitor_thread_.join();
    }
}

uintmax_t DirectorySpaceMonitor::get_total_size() const {
    return total_size_.load();
}

void DirectorySpaceMonitor::set_update_callback(std::function<void(uintmax_t)> callback) {
    std::lock_guard lock(callback_mutex_);
    update_callback_ = std::move(callback);
}


void DirectorySpaceMonitor::initial_scan() {
    std::lock_guard lock(cache_mutex_);
    file_cache_.clear();
    total_size_.store(0);

    for (const auto& entry : fs::recursive_directory_iterator(
            dir_path_, fs::directory_options::skip_permission_denied)) {

        if (entry.is_regular_file())  {
            try {
                auto size = entry.file_size();
                std::string path_str = entry.path().string();
                file_cache_[path_str] = size;
                total_size_.fetch_add(size);
            }
            catch (const fs::filesystem_error&) {/* 忽略不可访问的文件 */}
        }
    }
}

void DirectorySpaceMonitor::monitor_loop() {
    while (running_) {
        auto start_time = std::chrono::steady_clock::now();
        scan_changes();
        auto end_time = std::chrono::steady_clock::now();

        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
        auto sleep_duration = scan_interval_ - elapsed;

        if (sleep_duration > std::chrono::milliseconds(0)) {
            std::this_thread::sleep_for(sleep_duration);
        }
    }
}

void DirectorySpaceMonitor::scan_changes() {
    std::map<std::string, uintmax_t> current_files;
    uintmax_t current_total = 0;

    // 扫描当前文件状态（无锁操作）
    for (const auto &entry: fs::recursive_directory_iterator(
            dir_path_, fs::directory_options::skip_permission_denied)) {

        if (entry.is_regular_file()) {
            try {
                auto size = entry.file_size();
                std::string path_str = entry.path().string();
                current_files[path_str] = size;
                current_total += size;
            }
            catch (const fs::filesystem_error &) {/* 忽略错误 */}
        }
    }

    // 加锁更新缓存
    std::lock_guard lock(cache_mutex_);

    // 检测文件删除
    for (auto it = file_cache_.begin(); it != file_cache_.end();) {
        if (current_files.find(it->first) == current_files.end()) {
            total_size_.fetch_sub(it->second);
            it = file_cache_.erase(it);
        } else {
            ++it;
        }
    }

    // 检测新增/修改的文件
    for (const auto &[path, size]: current_files) {
        auto it = file_cache_.find(path);

        if (it == file_cache_.end()) {  // 新增文件
            file_cache_[path] = size;
            total_size_.fetch_add(size);
        } else if (it->second != size) {  // 文件大小变化
            int64_t diff = static_cast<int64_t>(size) - static_cast<int64_t>(it->second);
            total_size_.fetch_add(diff);
            it->second = size;
        }
    }

    // 触发回调
    if (update_callback_) {
        std::lock_guard cb_lock(callback_mutex_);
        update_callback_(total_size_.load());
    }
}